#include "VistaEscenario.h"
#include "Mutex.h"
#include <string>
#include <gtkmm.h>
#include <iostream>
#include "Configuracion.h"
#include "Partida.h"

VistaEscenario::VistaEscenario() {
    Glib::signal_timeout().connect(
        sigc::mem_fun(*this, &VistaEscenario::on_timeout), TIMEOUT_ON_DRAW);

    add_events(Gdk::BUTTON_PRESS_MASK);

    fichas = 0;

    filas = columnas = 0;

    cambiando = false;

    ini();
}

VistaEscenario::~VistaEscenario() { }

void VistaEscenario::setImagenFondo(std::string path) {
    backgroundImage =
        Gdk::Pixbuf::create_from_file(
            path)->scale_simple(
            600, 600, Gdk::INTERP_BILINEAR);
}

void VistaEscenario::notificarCambioTablero(bool cambio) {
    cambiando = cambio;
}

void VistaEscenario::quitarFichas() {
    protectorFichas.lock();
    Log::loguear(MINFO,"Quitando fichas del tablero...");
    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < columnas; j++) {
            if (vistaFichas[i][j] != NULL) {
                delete vistaFichas[i][j];
                vistaFichas[i][j] = NULL;
            }
        }
    }
    protectorFichas.unlock();
}

void VistaEscenario::ini() {
    for (int i = 0; i < MAX_CANTIDAD_FILAS; i++) {
        for (int j = 0; j < MAX_CANTIDAD_COLUMNAS; j++) {
            vistaFichas[i][j] = NULL;
        }
    }
}

void VistaEscenario::establecerDimensiones(int filas, int columnas) {
    this->filas = filas;
    this->columnas = columnas;

    ini();
}

int VistaEscenario::ajustarCoordenada(float coordenada) {
    int coordAjustada = 0;

    coordAjustada = coordenada * 50 + ((coordenada + 1) * 3);

    coordAjustada += 50;//es el margen

    return coordAjustada;
}

VistaEscenario::type_signal_something VistaEscenario::signal_something() {
    return m_signal_something;
}

bool VistaEscenario::on_timeout() {
    Glib::RefPtr<Gdk::Window> window = get_window();

    if (window) {
        Gdk::Rectangle rectangulo(0, 0, get_allocation().get_width(),
                                  get_allocation().get_height());
        window->invalidate_rect(rectangulo, false);
    }

    return true;
}

void VistaEscenario::dibujarFondo(const Cairo::RefPtr<Cairo::Context> &cr) {
    Gdk::Cairo::set_source_pixbuf(cr, backgroundImage, 0, 0);
    cr->paint();
}

void VistaEscenario::dibujarGrilla(const Cairo::RefPtr<Cairo::Context> &cr) {
    //hago transparente el fondo del tablero
    cr->set_source_rgba(0, 0, 0, 0.3);

    //DIBUJO TABLERO
    cr->rectangle(50, 50, 53 * columnas, 53 * filas);
    cr->fill();

    cr->set_line_width(3.0);

    //DIBUJO GRILLA
    cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);

    //columnas
    for (int i = 0; i <= columnas; i++) {
        cr->move_to(50 + 53 * i, 50);
        cr->line_to(50 + 53 * i, (filas + 1) * 53 - 2);
    }

    //filas
    for (int i = 0; i <= filas; i++) {
        cr->move_to(50, 50 + 53 * i);
        cr->line_to((columnas + 1) * 53 - 2, 50 + 53 * i);
    }

    cr->stroke();
}

void VistaEscenario::dibujarFichas(const Cairo::RefPtr<Cairo::Context> &cr) {
    protectorFichas.lock();

    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < columnas; j++) {
            if (vistaFichas[i][j] != NULL) {
                Gdk::Cairo::set_source_pixbuf(cr, vistaFichas[i][j]->buffer,
                                              vistaFichas[i][j]->yDesde, 
                                              vistaFichas[i][j]->xDesde);
                cr->paint();
            }
        }
    }
    protectorFichas.unlock();
}

void VistaEscenario::agregarFicha(VistaFichaTablero *ficha) {
    fichas++;

    vistaFichas[ficha->x][ficha->y] = ficha;
}

bool VistaEscenario::on_draw(const Cairo::RefPtr<Cairo::Context> &cr) {
        dibujarFondo(cr);

        dibujarGrilla(cr);

        dibujarFichas(cr);        
return true;
}

bool VistaEscenario::on_button_press_event(GdkEventButton *event) {
    int xE = event->x; //53: 50 ancho de ficha, 3 ancho del divisor del tablero
    xE -= 53;
    int posX = xE / 53;
    int yE = event->y;
    yE -= 53;
    int posY = yE / 53;

    m_signal_something.emit(posY, posX);

    return true;
}
